var c = document.getElementById('c'),
    ctx = c.getContext('2d'),
    shapes = [],
    circle1 = new Circle(150, 75, 20),
    circle2 = new Circle(350, 25, 30),
    polygonPoints = [
        [ new Point(250, 150), new Point(250, 250), new Point(350, 250) ],
        [ new Point(100, 100), new Point(100, 150), new Point(150, 150), new Point(150, 100) ],
        [ new Point(400, 100), new Point(380, 150), new Point(500, 150), new Point(520, 100) ]
    ],
    polygonStrokeColors = [ 'blue', 'yellow', 'red' ],
    polygonFillStyle = [ 'rgba(255, 255, 0, .7)', 'rgba(100, 140, 230, .6)', 'rgba(255, 0, 255, .8)' ],
    mousedown = { x: 0, y: 0 },
    lastdrag = { x: 0, y: 0 },
    dragVector = { x: 0, y: 0},
    stuck = false,
    patternSprite = new Sprite('ball', new Sprite.ImagePainter('../../../images/pattern.png')),  
    shapeBeingDragged = undefined;
window.addEventListener('resize', handleWindowResize, false);
function handleWindowResize () {
    c.width = window.innerWidth * window.devicePixelRatio;
    c.height = window.innerHeight * window.devicePixelRatio;
}
handleWindowResize()

// 函数·····························································
function windowToCanvas (x, y) {
    var bbox = c.getBoundingClientRect();
    return {
        x: x - bbox.left * (c.width / bbox.width),
        y: y - bbox.top * (c.height / bbox.height)
    }
}

function drawShapes () {
    shapes.forEach(function (shape) {
        shape.stroke(ctx);
        shape.fill(ctx);
    })
}

/**
 * 根据最小平移向量判断是否碰撞
 * @param {MinimumTranslationVector} mtv 最小平移向量
 */
function collisionDetected (mtv) {
    var result = false;
    if(mtv.axis === undefined) {
        //圆
        if(mtv.overlap > 0) {
            result = true;
        }
    } else {
        //多边形
        if(mtv.overlap !== 0) result = true;
    }
    return result;
}

//碰撞检测
function detectCollisions() {
    var textY = 30,
        numShapes = shapes.length,
        shape,
        result,
        i;
    if(shapeBeingDragged) {
        for(i = 0; i < numShapes; i += 1) {
            shape = shapes[i];
            if(shape !== shapeBeingDragged) {
                var mtv = shapeBeingDragged.collidesWith(shape);
                result = collisionDetected(mtv); //最小平移向量判断是否碰撞
                if(result) {
                    ctx.fillStyle = shape.fillStyle;
                    ctx.fillText('collsion', 20, textY);
                    textY += 40;
                    /* ===============额外处理=============== */
                    if(!stuck) {
                        stick(mtv);
                    }
                    /* ===============额外处理=============== */
                }
            }
        }
    }
}

/**
 * 根据最小平移向量将碰撞的两个图形分离
 * @param {MinimumTranslationVector} mtv 最小平移向量
 */
function separate (mtv) {
    var dx, dy, velocityMagnitude, point,
        velocity = {
            x: dragVector.x,
            y: dragVector.y
        };
    if(mtv.axis === undefined) {
        //移动图形是圆
        point = new Point();
        velocityMagnitude = Math.sqrt( Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2) );
        //point 是一个单位向量在x轴和y轴上的分量的模
        point.x = velocity.x / velocityMagnitude;
        point.y = velocity.y / velocityMagnitude;
        mtv.axis = new VectorB(point.x, point.y);
    }
    dy = mtv.axis.y * mtv.overlap;
    dx = mtv.axis.x * mtv.overlap;
    if( (dx < 0 && velocity.x < 0) || (dx > 0 && velocity.y > 0) ) {
        //偏移方向，与速度方向相同时，要逆向
        dx = -dx;
    }
    if( (dy > 0 && velocity.y > 0) || (dy < 0 && velocity.y < 0) ) {
        dy = -dy;
    }
    shapeBeingDragged.move(dx, dy);
}

//粘（zhan）粘（nian）函数
function stick (mtv) {
    var dx, dy, velocityMagnitude, point,
        velocity = {
            x: dragVector.x,
            y: dragVector.y
        };
    if(mtv.axis === undefined) {
        //移动图形是圆
        point = new Point();
        velocityMagnitude = Math.sqrt( Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2) );
        point.x = velocity.x / velocityMagnitude;
        point.y = velocity.y / velocityMagnitude;
        mtv.axis = new VectorB(point.x, point.y);
    }
    dx = mtv.axis.x * mtv.overlap;
    dy = mtv.axis.y * mtv.overlap;
    if( (dx > 0 && velocity.x > 0) || (dx < 0 && velocity.x < 0) ) {
        dx *= -1;
    }
    if( (dy > 0 && velocity.y > 0) || (dy < 0 && velocity.y < 0) ) {
        dy *= -1;
    }
    //等待500毫秒在移动
    setTimeout( function () {
        ShapeMoving.move(dx, dy);
    }, 500);
    dragVector.x = 0;
    dragVector.y = 0;
    //在粘贴期间不要在粘粘
    stuck = true;
}

function checkMTVAxisDirection(mtv, collider, collidee) {
    var centroid1, centroid2, centroidVector, centroidUnitVector;
    if(mtv.axis === undefined) {
        return;
    }
    centroid1 = new VectorB(collider.centroid());
    centroid2 = new VectorB(collidee.centroid());
    centroidVector = centroid2.sub(centroid1);
    centroidUnitVector = (new VectorB(centroidVector)).normalize();
    if(centroidUnitVector.dotProduct(mtv.axis) > 0) {
        mtv.axis.x = -mtv.axis.x;
        mtv.axis.y = -mtv.axis.y;
    }
}

/**
 * 反弹函数
 * @param {MinimumTranslationVector} mtv 最小平移向量
 * @param {Shape} collider 主动碰撞图形对象
 * @param {Shape} collidee 受碰对象
 */
function bounce(mtv, collider, collidee) {
    var dotProductRatio, vdotl, ldotl, point,
        velocityVector = new VectorB(new Point(velocity.x, velocity.y)),
        velocityUnitVector = velocityVector.normalize(),
        velocityVectorMagnitude = velocityVector.getMagnitude(),
        perpendicular;
    //shapeMoving是全局对象，表示正在移动的图形对象
    if(shapeMoving) {
        checkMTVAxisDirection(mtv, collider, collidee);

        point = new Point();
        if(mtv.axis !== undefined) {
            perpendicular = mtv.axis.perpendicular();
        } else {
            perpendicular = new VectorB(new Point(-velocityUnitVector.y, velocityUnitVector.x));
        }
        vdotl = velocityUnitVector.dotProduct(perpendicular);
        ldotl = perpendicular.dotProduct(perpendicular);
        dotProductRatio = vdotl / ldotl;
        point.x = 2 * dotProductRatio * perpendicular.x - velocityUnitVector.x;
        point.y = 2 * dotProductRatio * perpendicular.y - velocityUnitVector.y;
        separate(mtv);
        velocity.x = point.x * velocityVectorMagnitude;
        velocity.y = point.y * velocityVectorMagnitude;
    }
}

// 事件处理························································
c.addEventListener('mousedown', handleCanvasMousedown, false);
c.addEventListener('mousemove', handleCanvasMousemove, false);
c.addEventListener('mouseup', handleCanvasMouseup, false);

function handleCanvasMousedown (e) {
    var location = windowToCanvas(e.clientX, e.clientY);
    shapes.forEach( function (shape) {
        if(shape.isPointInPath(ctx, location.x, location.y)) {
            shapeBeingDragged = shape;
            mousedown.x = location.x;
            mousedown.y = location.y;
            lastdrag.x = location.x;
            lastdrag.y = location.y;
        }
    })
}

function handleCanvasMousemove (e) {
    var location;
    if(shapeBeingDragged !== undefined) {
        location = windowToCanvas(e.clientX, e.clientY);
        dragVector = {
            x: location.x - lastdrag.x,
            y: location.y - lastdrag.y
        };
        shapeBeingDragged.move(dragVector.x, dragVector.y);
        lastdrag.x = location.x;
        lastdrag.y = location.y;

        ctx.clearRect(0, 0, c.width, c.height);
        drawShapes();
        detectCollisions();
    }
}

function handleCanvasMouseup (e) {
    shapeBeingDragged = undefined;
}

// 初始化························································
for(var i = 0; i < polygonPoints.length; i += 1) {
    var polygon = new Polygon(),
        points = polygonPoints[i];
    polygon.strokeStyle = polygonStrokeColors[i];
    polygon.fillStyle = polygonFillStyle[i];
    points.forEach(function (point) {
        polygon.addPoint(point.x, point.y);
    })
    shapes.push(polygon);
}
shapes.push(circle1);
shapes.push(circle2);
shapes.push(new ImageShape('../../../images/tree_01.png', 400, 150, 200, 200));
patternSprite.width = 86;
patternSprite.height = 117;
shapes.push(new SpriteShape(patternSprite, 350, 188));

ctx.shadowColow = 'rgba(100, 140, 255, .5)';
ctx.shadowBlur = 4;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.font = '38px Arial';

drawShapes();

ctx.save();
ctx.fillStyle = 'cornflowerblue';
ctx.font = '24px Arial';
ctx.fillText('拖拽图形', 10, 25);
ctx.restore();